import React, { useState, useEffect, useRef, ReactNode } from 'react';
import { Tree, Input } from 'antd';
import { DataNode } from 'antd/lib/tree';
import _ from 'lodash';

import './index.less';
import { storage } from '@ey-utils/utils';

export type Key = string | number;

export interface BasicTreeProps {
  showLine?: boolean; // 是否展示连接线
  treeData?: DataNode[]; // 树数据
  canSearch?: boolean; // 是否可查询
  onlyLeaf?: boolean; // 只能选中叶子节点
  cantUnSelect?: boolean; // 禁止取消选择
  defaultSelectedKeys?: any[], // 默认选中keys
  onSelect: (node: DataNode) => boolean | void; // 节点选择回调(根据返回值判断是否可选中)
  defaultExpandedKeys?: any[];
  renderNode?: (node: DataNode, title: any) => ReactNode; // 处理自定义节点渲染
}

interface FlatItem extends DataNode {
  parentKey: Key;
  parentName: ReactNode;
}

const { Search } = Input;

const setTreeCache = (selectedKeys: any, info: any) => {
  storage.setItem(location.hash, selectedKeys);
  storage.setItem(`info,${location.hash}`, {
    title: info.node.name,
    code: info.node.key,
    parentPath: info?.node?.parentPath || [],
  });
}

export const getTreeCache = () => {
  const uri = location.hash;
  const uriInfo = `info,${location.hash}`;
  return {
    code: storage.getItem(uri)[0] ? storage.getItem(uri) : [],
    data: storage.getItem(uriInfo)
  }
}

export const findTreeNode = (treeData: any[], findKey: string) => {
  let findNode: any = null;

  treeData.some((item: any) => {
    if (item.key === findKey) {
      findNode = item;
      return true;
    }

    if (item.children && item.children.length) {
      findNode = findTreeNode(item.children, findKey);
    }

    if (findNode) {
      return true;
    }

    return false;
  });

  return findNode;
}

const BasicTree: React.FC<BasicTreeProps> = ({
  showLine = false,
  treeData = [],
  canSearch = false,
  onlyLeaf = false,
  cantUnSelect = false,
  defaultSelectedKeys = [],
  onSelect,
  defaultExpandedKeys,
  renderNode,
}) => {
  const [expandedKeys, setExpandedKeys] = useState<Key[]>(defaultExpandedKeys || []);
  const [selectedKeys, setSelectedKeys] = useState<Key[]>(defaultSelectedKeys);

  const [autoExpandParent, setAutoExpandParent] = useState(true);
  const [flatData, setFlatData] = useState<FlatItem[]>([]);

  const searchValRef = useRef<string>();

  useEffect(() => {
    setFlatData(flatTree([], treeData, ''));
  }, [treeData])

  /**
   * 打平treeData
   * @param data
   * @param nodes
   * @param parentKey
   * @param parentName
   * @returns
   */
  const flatTree = (data: FlatItem[], nodes: DataNode[], parentKey: Key, parentName?: ReactNode): FlatItem[] => {
    if (!nodes || nodes.length === 0) {
      return [];
    };

    nodes.forEach((node: DataNode) => {
      data.push({
        parentKey,
        parentName,
        ...node,
      });
      flatTree(data, node.children || [], node.key, node.title);
    });

    return data;
  }

  /**
   * 节点查询
   * @param evt
   */
  const handleSearch = (evt: React.ChangeEvent<HTMLInputElement>) => {
    const { value } = evt.target;

    if (!_.trim(value)) {
      searchValRef.current = '';
      setExpandedKeys([]);
      return;
    }

    const expandedKeys: Key[] = [];

    flatData.map((item: FlatItem) => {
      if ((item.title as string).indexOf(value) > -1) {
        expandedKeys.push(item.parentKey);
      }
    });

    searchValRef.current = value;
    setExpandedKeys(expandedKeys);
    setAutoExpandParent(true);

    // 完全匹配时选中
    const node = _.filter(flatData, { title: value }).shift();
    if (node && !onSelect(node)) {
      setSelectedKeys([node.key]);
    }
  }

  /**
   * 节点展开
   * @param expandedKeys
   */
  const handleExpand = (expandedKeys: Key[]) => {
    setExpandedKeys(expandedKeys);
    setAutoExpandParent(false);
  }

  /**
   * 节点选中
   * @param keys
   * @param info
   */
  const handleSelect = (selectedKeys: Key[], info: any) => {
    const flatItem: FlatItem | undefined = _.filter(flatData, { key: selectedKeys[0] }).shift();

    setTreeCache(selectedKeys, info);
    if (cantUnSelect && !info.selected) return;
    if ((onlyLeaf && !flatItem?.isLeaf) || onSelect(flatItem as DataNode)) {
      return;
    }
    setSelectedKeys(selectedKeys);
  }

  /**
   * 搜索高亮
   * @param data
   * @returns
   */
  const loop = (data: DataNode[]): DataNode[] => {
    console.log('data', data);
    return data.map((item: DataNode) => {
      let initTitle: string = item.title as string || '';
      const searchValue = searchValRef.current || '';
      const index = initTitle.indexOf(searchValue);
      const beforeStr = initTitle.substr(0, index);
      const afterStr = initTitle.substr(index + searchValue.length);

      const title = (index > -1 && searchValue) ? (
        <span className='highLight-warp'>
          {beforeStr}
          <span className="site-tree-search-value">{searchValue}</span>
          {afterStr}
        </span>
      ) : (
        <span>{item.title}</span>
      );
      const ft = renderNode ? renderNode(item, title) : title
      if (item.children) {
        // fix: 组件填加parentPath但是还有很多节点被过滤了？
        return { disabled: !!item?.disabled, title: ft, key: item.key, name: initTitle, children: loop(item.children), parentPath: (item?.parentPath || []) };
      }
      return {
        ...item,
        title: ft,
        name: initTitle,
        key: item.key,
      };
    });
  }
  return (
    <>
      {
        canSearch ? <Search style={{ marginBottom: 8 }} onChange={handleSearch} /> : null
      }
      <Tree
        showLine={showLine}
        onExpand={handleExpand}
        onSelect={handleSelect}
        expandedKeys={expandedKeys}
        selectedKeys={selectedKeys}
        // defaultExpandedKeys={}
        autoExpandParent={autoExpandParent}
        treeData={loop(treeData)}
      />
    </>
  );
}

export default BasicTree;
